package com.example.file.controller;

import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import com.example.common.support.ApiException;
import com.example.common.support.Result;
import com.example.file.properties.MinIoProp;
import com.example.file.utils.FileUtils;
import io.minio.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;

/**
 * @Author wxy
 * @Date 2020/11/12 16:58
 * @Version 1.0
 */
@Slf4j
@RestController
@Api(tags = "文件管理")
@RequestMapping("/file")
public class FileController {
    @Resource
    private MinIoProp minIoProp;
    @Resource
    private HttpServletRequest request;

    @ApiOperation(value = "文件上传", notes = "文件上传")
    @PostMapping(value = "/fileUpload")
    public Result<Object> fileUpload(@RequestParam(value = "file") MultipartFile multipartFile) throws Exception {
        if (multipartFile.getSize() >= 1024 * 1024 * 100) {
            throw new ApiException(1, "文件上传大小不得超过100M");
        }
        log.info("请求ip:" + request.getRemoteAddr());
        //文件流
        InputStream inputStream = multipartFile.getInputStream();
        //文件大小
        long size = multipartFile.getSize();
        //文件contentType
        String contentType = multipartFile.getContentType();
        //文件md5
        String md5 = new Digester(DigestAlgorithm.MD5).digestHex(multipartFile.getInputStream());
        //源文件名
        String originalFilename = multipartFile.getOriginalFilename();
        assert originalFilename != null;
        //取原文件名后缀
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        //定义新文件名
        String fileName = md5 + "." + suffix;
        //打开文件监听
        MinioClient minioClient = MinioClient.builder().endpoint(minIoProp.getUrl()).credentials(minIoProp.getAccessKey(), minIoProp.getSecretKey()).build();
        //桶
        String bucket = minIoProp.getBucket();
        //若桶不存在，则创建桶
        boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
        if (!isExist) {
            //创建存储桶
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
            //设置桶策略
            String policyJson = FileUtils.policy(bucket);
            minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(policyJson).build());
        }
        //上传
        minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(fileName).stream(inputStream, size, -1).contentType(contentType).build());
        String url = minIoProp.getBaseUrl() + "/" + bucket + "/" + fileName;
        log.info("文件上传成功!地址:" + url);
        return Result.success(url);
    }

    /**
     * 文件上传不修改文件名
     * @param multipartFile
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "文件上传", notes = "文件上传")
    @PostMapping(value = "/fileUploadNOtRen")
    public Result<Object> fileUploadNOtRen(@RequestParam(value = "file") MultipartFile multipartFile) throws Exception {
        if (multipartFile.getSize() >= 1024 * 1024 * 100) {
            throw new ApiException(1, "文件上传大小不得超过100M");
        }
        log.info("请求ip:" + request.getRemoteAddr());
        //文件流
        InputStream inputStream = multipartFile.getInputStream();
        //文件大小
        long size = multipartFile.getSize();
        //文件contentType
        String contentType = multipartFile.getContentType();

        //源文件名
        String originalFilename = multipartFile.getOriginalFilename();
        assert originalFilename != null;

        //打开文件监听
        MinioClient minioClient = MinioClient.builder().endpoint(minIoProp.getUrl()).credentials(minIoProp.getAccessKey(), minIoProp.getSecretKey()).build();

        //桶
        String bucket = minIoProp.getBucket();

        //若桶不存在，则创建桶
        boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
        if (!isExist) {
            //创建存储桶
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
            //设置桶策略
            String policyJson = FileUtils.policy(bucket);
            minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(policyJson).build());
        }
        //上传
        minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(originalFilename).stream(inputStream, size, -1).contentType(contentType).build());
        String url = minIoProp.getBaseUrl() + "/" + bucket + "/" + originalFilename;
        log.info("文件上传成功!地址:" + url);
        return Result.success(url);
    }

    @ApiOperation(value = "文件上传(内部调用)", notes = "文件上传(内部调用)")
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Result<Object> upload(@RequestPart(value = "file") MultipartFile multipartFile) throws Exception {
        return fileUpload(multipartFile);
    }
}
